home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #5
/
Amiga Plus CD - 2000 - No. 5.iso
/
Tools
/
Dev
/
FPSE_src
/
bios.c
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
34KB
|
1,260 lines
/*
HLE bios emulation
==================
Written by BERO
*/
#include "fpse.h"
#define PSADDR2(addr,base) ((int)addr-(int)base)
#define PSADDR(addr,base) (int)(addr?PSADDR2(addr,base):(int)addr)
#define PCADDR(addr,base) (addr?(addr+base):(void*)addr)
static int bios_a0();
static int bios_b0();
static int bios_c0();
static char *a0name[] = {
/* 0x00 */ "open",
/* 0x01 */ "lseek",
/* 0x02 */ "read",
/* 0x03 */ "write",
/* 0x04 */ "close",
/* 0x05 */ "ioctl",
/* 0x06 */ "exit",
/* 0x07 */ "bios_a0_07",
/* 0x08 */ "getc",
/* 0x09 */ "putc",
/* 0x0a */ "todigit",
/* 0x0b */ "atof",
/* 0x0c */ "strtoul",
/* 0x0d */ "strtol",
/* 0x0e */ "abs",
/* 0x0f */ "labs",
/* 0x10 */ "atoi",
/* 0x11 */ "atol",
/* 0x12 */ "atob",
/* 0x13 */ "setjmp",
/* 0x14 */ "longjmp",
/* 0x15 */ "strcat",
/* 0x16 */ "strncat",
/* 0x17 */ "strcmp",
/* 0x18 */ "strncmp",
/* 0x19 */ "strcpy",
/* 0x1a */ "strnpy",
/* 0x1b */ "strlen",
/* 0x1c */ "index",
/* 0x1d */ "rindex",
/* 0x1e */ "strchr",
/* 0x1f */ "strrchr",
/* 0x20 */ "strpbrk",
/* 0x21 */ "strspn",
/* 0x22 */ "strcspn",
/* 0x23 */ "strtok",
/* 0x24 */ "strstr",
/* 0x25 */ "toupper",
/* 0x26 */ "tolower",
/* 0x27 */ "bcopy",
/* 0x28 */ "bzero",
/* 0x29 */ "bcmp",
/* 0x2a */ "memcpy",
/* 0x2b */ "memset",
/* 0x2c */ "memmove",
/* 0x2d */ "memcmp",
/* 0x2e */ "memchr",
/* 0x2f */ "rand",
/* 0x30 */ "srand",
/* 0x31 */ "qsort",
/* 0x32 */ "strtod",
/* 0x33 */ "malloc",
/* 0x34 */ "free",
/* 0x35 */ "lsearch",
/* 0x36 */ "bsearch",
/* 0x37 */ "calloc",
/* 0x38 */ "realloc",
/* 0x39 */ "InitHeap",
/* 0x3a */ "_exit",
/* 0x3b */ "getchar",
/* 0x3c */ "putchar",
/* 0x3d */ "gets",
/* 0x3e */ "puts",
/* 0x3f */ "printf",
/* 0x40 */ "bios_a0_40",
/* 0x41 */ "LoadTest",
/* 0x42 */ "Load",
/* 0x43 */ "Exec",
/* 0x44 */ "FlushCache",
/* 0x45 */ "InstallInterruptHandler",
/* 0x46 */ "GPU_dw",
/* 0x47 */ "mem2vram",
/* 0x48 */ "SendGPU",
/* 0x49 */ "GPU_cw",
/* 0x4a */ "GPU_cwb",
/* 0x4b */ "SendPackets",
/* 0x4c */ "bios_a0_4c",
/* 0x4d */ "GetGPUStatus",
/* 0x4e */ "GPU_sync",
/* 0x4f */ "bios_a0_4f",
/* 0x50 */ "bios_a0_50",
/* 0x51 */ "LoadExec",
/* 0x52 */ "GetSysSp",
/* 0x53 */ "bios_a0_53",
/* 0x54 */ "_96_init",
/* 0x55 */ "_bu_init",
/* 0x56 */ "_96_remove",
/* 0x57 */ "bios_a0_57",
/* 0x58 */ "bios_a0_58",
/* 0x59 */ "bios_a0_59",
/* 0x5a */ "bios_a0_5a",
/* 0x5b */ "dev_tty_init",
/* 0x5c */ "dev_tty_open",
/* 0x5d */ "dev_tty_5d",
/* 0x5e */ "dev_tty_ioctl",
/* 0x5f */ "dev_cd_open",
/* 0x60 */ "dev_cd_read",
/* 0x61 */ "dev_cd_close",
/* 0x62 */ "dev_cd_firstfile",
/* 0x63 */ "dev_cd_nextfile",
/* 0x64 */ "dev_cd_chdir",
/* 0x65 */ "dev_card_open",
/* 0x66 */ "dev_card_read",
/* 0x67 */ "dev_card_write",
/* 0x68 */ "dev_card_close",
/* 0x69 */ "dev_card_firstfile",
/* 0x6a */ "dev_card_nextfile",
/* 0x6b */ "dev_card_erase",
/* 0x6c */ "dev_card_undelete",
/* 0x6d */ "dev_card_format",
/* 0x6e */ "dev_card_rename",
/* 0x6f */ "dev_card_6f",
/* 0x70 */ "_bu_init(a0_70)",
/* 0x71 */ "_96_init(a0_71)",
/* 0x72 */ "_96_remove(a0_72)",
/* 0x73 */ "bios_a0_73",
/* 0x74 */ "bios_a0_74",
/* 0x75 */ "bios_a0_75",
/* 0x76 */ "bios_a0_76",
/* 0x77 */ "bios_a0_77",
/* 0x78 */ "_96_CdSeekL",
/* 0x79 */ "bios_a0_79",
/* 0x7a */ "bios_a0_7a",
/* 0x7b */ "bios_a0_7b",
/* 0x7c */ "_96_CdGetStatus",
/* 0x7d */ "bios_a0_7d",
/* 0x7e */ "_96_CdRead",
/* 0x7f */ "bios_a0_7f",
/* 0x80 */ "bios_a0_80",
/* 0x81 */ "bios_a0_81",
/* 0x82 */ "bios_a0_82",
/* 0x83 */ "bios_a0_83",
/* 0x84 */ "bios_a0_84",
/* 0x85 */ "_96_CdStop",
/* 0x86 */ "bios_a0_86",
/* 0x87 */ "bios_a0_87",
/* 0x88 */ "bios_a0_88",
/* 0x89 */ "bios_a0_89",
/* 0x8a */ "bios_a0_8a",
/* 0x8b */ "bios_a0_8b",
/* 0x8c */ "bios_a0_8c",
/* 0x8d */ "bios_a0_8d",
/* 0x8e */ "bios_a0_8e",
/* 0x8f */ "bios_a0_8f",
/* 0x90 */ "bios_a0_90",
/* 0x91 */ "bios_a0_91",
/* 0x92 */ "bios_a0_92",
/* 0x93 */ "bios_a0_93",
/* 0x94 */ "bios_a0_94",
/* 0x95 */ "bios_a0_95",
/* 0x96 */ "AddCDROMDevice",
/* 0x97 */ "AddMemCardDevice",
/* 0x98 */ "DisableKernelIORedirection",
/* 0x99 */ "EnableKernelIORedirection",
/* 0x9a */ "bios_a0_9a",
/* 0x9b */ "bios_a0_9b",
/* 0x9c */ "SetConf # may be",
/* 0x9d */ "GetConf # ",
/* 0x9e */ "bios_a0_9e",
/* 0x9f */ "SetMem",
/* 0xa0 */ "_boot",
/* 0xa1 */ "SystemError",
/* 0xa2 */ "EnqueueCdIntr",
/* 0xa3 */ "DequeueCdIntr",
/* 0xa4 */ "bios_a0_a4",
/* 0xa5 */ "ReadSector",
/* 0xa6 */ "get_cd_status",
/* 0xa7 */ "bufs_cb_0",
/* 0xa8 */ "bufs_cb_1",
/* 0xa9 */ "bufs_cb_2",
/* 0xaa */ "bufs_cb_3",
/* 0xab */ "_card_info",
/* 0xac */ "_card_load",
/* 0xad */ "_card_auto",
/* 0xae */ "bufs_cb_4",
/* 0xaf */ "bios_a0_af",
/* 0xb0 */ "bios_a0_b0",
/* 0xb1 */ "bios_a0_b1",
/* 0xb2 */ "do_a_long_jmp",
/* 0xb3 */ "bios_a0_b3",
/* 0xb4 */ "bios_a0_b4"
};
static char *b0name[] = {
/* 0x00 */ "SysMalloc",
/* 0x01 */ "bios_b0_01",
/* 0x02 */ "bios_b0_02",
/* 0x03 */ "bios_b0_03",
/* 0x04 */ "bios_b0_04",
/* 0x05 */ "bios_b0_05",
/* 0x06 */ "bios_b0_06",
/* 0x07 */ "DeliverEvent",
/* 0x08 */ "OpenEvent",
/* 0x09 */ "CloseEvent",
/* 0x0a */ "WaitEvent",
/* 0x0b */ "TestEvent",
/* 0x0c */ "EnableEvent",
/* 0x0d */ "DisableEvent",
/* 0x0e */ "OpenTh",
/* 0x0f */ "CloseTh",
/* 0x10 */ "ChangeTh",
/* 0x11 */ "bios_b0_11",
/* 0x12 */ "InitPAD",
/* 0x13 */ "StartPAD",
/* 0x14 */ "StopPAD",
/* 0x15 */ "PAD_init",
/* 0x16 */ "PAD_dr",
/* 0x17 */ "ReturnFromException",
/* 0x18 */ "ResetEntryInt",
/* 0x19 */ "HookEntryInt",
/* 0x1a */ "bios_b0_1a",
/* 0x1b */ "bios_b0_1b",
/* 0x1c */ "bios_b0_1c",
/* 0x1d */ "bios_b0_1d",
/* 0x1e */ "bios_b0_1e",
/* 0x1f */ "bios_b0_1f",
/* 0x20 */ "UnDeliverEvent",
/* 0x21 */ "bios_b0_21",
/* 0x22 */ "bios_b0_22",
/* 0x23 */ "bios_b0_23",
/* 0x24 */ "bios_b0_24",
/* 0x25 */ "bios_b0_25",
/* 0x26 */ "bios_b0_26",
/* 0x27 */ "bios_b0_27",
/* 0x28 */ "bios_b0_28",
/* 0x29 */ "bios_b0_29",
/* 0x2a */ "bios_b0_2a",
/* 0x2b */ "bios_b0_2b",
/* 0x2c */ "bios_b0_2c",
/* 0x2d */ "bios_b0_2d",
/* 0x2e */ "bios_b0_2e",
/* 0x2f */ "bios_b0_2f",
/* 0x30 */ "bios_b0_30",
/* 0x31 */ "bios_b0_31",
/* 0x32 */ "open(b0)",
/* 0x33 */ "lseek(b0)",
/* 0x34 */ "read(b0)",
/* 0x35 */ "write(b0)",
/* 0x36 */ "close(b0)",
/* 0x37 */ "ioctl(b0)",
/* 0x38 */ "exit(b0)",
/* 0x39 */ "bios_b0_39",
/* 0x3a */ "getc(b0)",
/* 0x3b */ "putc(b0)",
/* 0x3c */ "getchar(b0)",
/* 0x3d */ "putchar(b0)",
/* 0x3e */ "gets(b0)",
/* 0x3f */ "puts(b0)",
/* 0x40 */ "cd",
/* 0x41 */ "format",
/* 0x42 */ "firstfile",
/* 0x43 */ "nextfile",
/* 0x44 */ "rename",
/* 0x45 */ "delete",
/* 0x46 */ "undelete",
/* 0x47 */ "AddDevice",
/* 0x48 */ "RemoteDevice",
/* 0x49 */ "PrintInstalledDevices",
/* 0x4a */ "InitCARD",
/* 0x4b */ "StartCARD",
/* 0x4c */ "StopCARD",
/* 0x4d */ "bios_b0_4d",
/* 0x4e */ "_card_write",
/* 0x4f */ "_card_read",
/* 0x50 */ "_new_card",
/* 0x51 */ "Krom2RawAdd",
/* 0x52 */ "bios_b0_52",
/* 0x53 */ "bios_b0_53",
/* 0x54 */ "_get_errno",
/* 0x55 */ "_get_error",
/* 0x56 */ "GetC0Table",
/* 0x57 */ "GetB0Table",
/* 0x58 */ "_card_chan",
/* 0x59 */ "bios_b0_59",
/* 0x5a */ "bios_b0_5a",
/* 0x5b */ "ChangeClearPAD",
/* 0x5c */ "_card_status",
/* 0x5d */ "_card_wait"
};
static char *c0name[]={
/* 0x00 */ "InitRCnt",
/* 0x01 */ "InitException",
/* 0x02 */ "SysEnqIntRP",
/* 0x03 */ "SysDeqIntRP",
/* 0x04 */ "get_free_EvCB_slot",
/* 0x05 */ "get_free_TCB_slot",
/* 0x06 */ "ExceptionHandler",
/* 0x07 */ "InstallExceptionHandler",
/* 0x08 */ "SysInitMemory",
/* 0x09 */ "SysInitKMem",
/* 0x0a */ "ChangeClearRCnt",
/* 0x0b */ "SystemError(c0)",
/* 0x0c */ "InitDefInt",
/* 0x0d */ "bios_c0_0d",
/* 0x0e */ "bios_c0_0e",
/* 0x0f */ "bios_c0_0f",
/* 0x10 */ "bios_c0_10",
/* 0x11 */ "bios_c0_11",
/* 0x12 */ "InstallDevices",
/* 0x13 */ "FlushStdInOutPut",
/* 0x14 */ "bios_c0_14",
/* 0x15 */ "_cdevinput",
/* 0x16 */ "_cdevscan",
/* 0x17 */ "_circgetc",
/* 0x18 */ "_circputc",
/* 0x19 */ "ioabort",
/* 0x1a */ "bios_c0_1a",
/* 0x1b */ "KernelRedirect",
/* 0x1c */ "PatchAOTable",
};
static void *realaddr(int addr) { return (char*)baseaddr(addr)+addr; }
#define v0 reg.r[2]
#define v1 reg.r[3]
#define a0 reg.r[4]
#define a1 reg.r[5]
#define a2 reg.r[6]
#define a3 reg.r[7]
#define sp reg.r[29]
#define stack ((int*)realaddr(reg.r[29]))
int biosprint(int pc)
{
int ret = 0;
int no = reg.r[9];
if (verbose) {
char *name = NULL;
switch(pc){
case 0xa0:
if (no<sizeof(a0name)/sizeof(a0name[0]))
name = a0name[no];
break;
case 0xb0:
if (no<sizeof(b0name)/sizeof(b0name[0]))
name = b0name[no];
break;
case 0xc0:
if (no<sizeof(c0name)/sizeof(c0name[0]))
name = c0name[no];
break;
}
if (name) {
printf("bios:%s ",name);
} else {
printf("bios:%02x,%x",(int)pc,(int)no);
}
}
if (!emulate_bios) {
switch(pc) {
case 0xa0:
switch(no) {
case 0x3f: // printf
PRINTF("%s",(char *)realaddr(a0)); break;
}
break;
case 0xb0:
switch(no) {
case 0x08: // OpenEvent
PRINTF("(%x,%x,%x,%x)",(int)a0,(int)a1,(int)a2,(int)a3);
break;
case 0x09: //
case 0x0C: //
case 0x0D: //
PRINTF("(%x)",(int)a0); break;
case 0x3c: // getchar
v0 = getchar(); PC = reg.r[31]; break;
case 0x3e: // gets
{
char *base = (char*)baseaddr(a0);
char *ret = gets(base + a0);
v0 = PSADDR(ret,base);
PC = reg.r[31];
}
break;
case 0x3f: // puts
v0 = puts(realaddr(a0)); PC = reg.r[31]; break;
case 0x3d: // putchar
putchar(a0); PC = reg.r[31]; break;
}
}
} else {
switch (pc) {
case 0xa0: ret = bios_a0(); break;
case 0xb0: ret = bios_b0(); break;
case 0xc0: ret = bios_c0(); break;
}
if ((pc!=0xb0) || (no!=0x17)) // ReturnFromException
PC = reg.r[31];
}
PRINTF("\n");
return ret;
}
static char *qbase;
static int qsub;
static int save_reg[32+3];
static int *jmpbuf;
static char *heapbase;
static int qcmp(const void *arg0,const void *arg1)
{
a0 = PSADDR2(arg0,qbase);
a1 = PSADDR2(arg1,qbase);
/* qsubðÀs */
return v0;
}
typedef struct {
char id[6];
char fontname[8];
UINT8 w,h;
UINT8 type;
UINT8 ntbl;
UINT16 codetbl[1];
} FONTXHDR;
static FONTXHDR *font;
/*
FONTX format
idx siz
0 6 "FONTX"
6 8 font name
14 1 width
15 1 height
16 1 type 0=ANK,1=Japanese
ANK:
17 font data
Japanese:
17 1 Number of code table
18 2 start of code (little endian)
19 2 end of code
.
.
18+N*4 font data
*/
void *Krom2RawAdd(int code)
{
UINT16 *ptbl = font->codetbl;
int size = ((font->w+7)/8)*font->h;
int n=0,i;
for(i=0;i<font->ntbl;i++) {
if (code>=ptbl[0] && code<=ptbl[1]) {
return (char*)&font->codetbl[font->ntbl*2] +
(code-ptbl[0]+n)*size+2; /* skip */
}
n += ptbl[1]-ptbl[0] + 1;
ptbl+=2;
}
return NULL;
}
#define strcmpz(a,b) memcmp(a,b,strlen(b))
static char *cd_path="e:";
static char *bu00_path="bu00\\";
static char *bu10_path="bu10\\";
static char *pcdrv_path="";
static char *real_path(char *name)
{
static char buf[256];
if (strcmpz(name,"cdrom:")==0) {
strcpy(buf,cd_path);
strcat(buf,name+6);
{
char *p = buf+strlen(buf);
p[-2]='\0';
/* "cdrom:filename;1" */
}
} else if (strcmpz(name,"bu00:")==0) {
strcpy(buf,bu00_path);
strcat(buf,name+5);
} else if (strcmpz(name,"bu10:")==0) {
strcpy(buf,bu10_path);
strcat(buf,name+5);
} else if (strcmpz(name,"pcdrv:")==0) {
strcpy(buf,pcdrv_path);
strcat(buf,name+6);
} else return NULL;
return buf;
}
static int bios_open(char *name,int psxmode)
{
/* psx define
#define O_RDONLY 1
#define O_WRONLY 2
#define O_RDWR 3
#define O_CREAT 0x200
*/
int mode=O_BINARY;
switch(psxmode&3) {
case 1: mode|=O_RDONLY; break;
case 2: mode|=O_WRONLY; break;
case 3: mode|=O_RDWR; break;
}
if (psxmode&0x200) mode|=O_CREAT;
PRINTF("%s",name);
return open(real_path(name),mode);
}
#if 0
static void bios_setjmp(int *jmpbuf)
{
jmpbuf[0] = reg.r[31]; /* ra */
jmpbuf[1] = reg.r[29]; /* sp */
jmpbuf[2] = reg.r[28]; /* fp */
jmpbuf[3] = reg.r[16]; /* s0 */
jmpbuf[4] = reg.r[17]; /* s1 */
jmpbuf[5] = reg.r[18]; /* s2 */
jmpbuf[6] = reg.r[19]; /* s3 */
jmpbuf[7] = reg.r[20]; /* s4 */
jmpbuf[8] = reg.r[21]; /* s5 */
jmpbuf[9] = reg.r[22]; /* s6 */
jmpbuf[10] = reg.r[23]; /* s7 */
jmpbuf[11] = reg.r[28]; /* gp */
}
#endif
static void bios_longjmp(int *jmpbuf)
{
reg.r[31] = jmpbuf[0]; /* ra */
reg.r[29] = jmpbuf[1]; /* sp */
reg.r[28] = jmpbuf[2]; /* fp */
reg.r[16] = jmpbuf[3]; /* s0 */
reg.r[17] = jmpbuf[4]; /* s1 */
reg.r[18] = jmpbuf[5]; /* s2 */
reg.r[19] = jmpbuf[6]; /* s3 */
reg.r[20] = jmpbuf[7]; /* s4 */
reg.r[21] = jmpbuf[8]; /* s5 */
reg.r[22] = jmpbuf[9]; /* s6 */
reg.r[23] = jmpbuf[10]; /* s7 */
reg.r[28] = jmpbuf[11]; /* gp */
}
static int match(char *s1, char *s2)
{
if (*s1=='.') return 0;
for ( ; ; ) {
while (*s2 == '*' || *s2 == '?') {
if (*s2++ == '*')
while (*s1 && toupper(*s1) != toupper(*s2)) s1++;
else
if (*s1 == 0) return 0;
else s1++;
}
if (toupper(*s1) != toupper(*s2)) return 0;
if (*s1 == 0 ) return 1;
s1++; s2++;
}
}
/* PSX struct */
struct DIRENTRY {
char name[20];
INT32 attr;
UINT32 size;
struct DIRENTRY *next;
INT32 head;
char system[4];
};
static DIR *hdir;
static char pathbuf[256/*MAXPATH*/];
static char matchname[20],*nameptr;
struct DIRENTRY* nextfile(struct DIRENTRY *dir)
{
struct dirent *dirent;
struct stat statbuf;
if (hdir==NULL) return NULL;
do {
dirent = readdir(hdir);
if (dirent == NULL) {
closedir(hdir);
hdir = NULL;
return NULL;
}
// printf("%s %s\n",dirent->d_name,matchname);
} while(!match(dirent->d_name,matchname));
// printf("match");
strcpy(dir->name,dirent->d_name);
strcpy(nameptr,dirent->d_name);
stat(pathbuf,&statbuf);
dir->size = statbuf.st_size;
return dir;
}
#define PATH_DELIMITER '\\'
struct DIRENTRY* firstfile(char *path,struct DIRENTRY *dir)
{
char *p,*matchpath;
// printf("path;%s\n",path);
strcpy(pathbuf,real_path(path));
p = strrchr(pathbuf,PATH_DELIMITER);
if (p) {
*p=0;
matchpath = pathbuf;
nameptr = p+1;
} else {
matchpath = ".";
nameptr = pathbuf;
}
strcpy(matchname,nameptr);
// printf("%s %s:\n",matchpath,matchname);
if (hdir) {
closedir(hdir);
}
hdir = opendir(matchpath);
if (hdir==NULL) return NULL;
if (p) {
*p = PATH_DELIMITER;
}
return nextfile(dir);
}
static char *padbuf1,*padbuf2;
static int padbuf1len,padbuf2len;
static int *padbuf;
static void pad_update(void)
{
int pad1,pad2;
pad1 = 0xFFFF; // JOY_Poll(0);
pad2 = 0xFFFF; // JOY_Poll(1);
if (padbuf) *padbuf = (pad1 | (pad2<<16));
if (padbuf1) {
padbuf1[0] = 0;
padbuf1[1] = 0x41;
padbuf1[2] = pad1 >> 8;
padbuf1[3] = pad1;
padbuf2[0] = 0;
padbuf2[1] = 0x41;
padbuf2[2] = pad2>>8;
padbuf2[3] = pad2;
}
}
static int bios_b0()
{
switch(reg.r[9]) {
case 0x12: /* InitPAD */
padbuf1 = realaddr(a0);
padbuf1len = a1;
padbuf2 = realaddr(a2);
padbuf2len = a3;
break;
case 0x13: /* StartPAD */
hw_write16(0x1f801074,hw_read16(0x1f801074)|1); /* Vsync Interrupt enable */
SR |= 0x401; /* interrupt enable */
break;
case 0x14: /* StopPAD */
break;
case 0x15: /* PAD_init */
padbuf = realaddr(a1);
*padbuf = -1;
hw_write16(0x1f801074,hw_read16(0x1f801074)|1); /* Vsync Interrupt enable */
SR |= 0x401; /* interrupt enable */
break;
case 0x16: /* PAD_dr */
break;
case 0x17: /* ReturnFromException */
SR = (SR & ~0xf)| ((SR>>2)&0xf);
/* WX^ðáO¶Éß· */
memcpy(reg.r,save_reg,sizeof(save_reg));
PC = EPC;
break;
case 0x19: /* HookEntryInt */
jmpbuf = realaddr(a0);
break;
case 0x32: /* open */
v0 = bios_open(realaddr(a0),a1); break;
case 0x33: /* lseek */
v0 = lseek(a0,a1,a2); break;
case 0x34: /* read */
printf("%d %x %d",(int)a0,(int)a1,(int)a2);
v0 = read(a0,realaddr(a1),a2); break;
case 0x35: /* write */
v0 = write(a0,realaddr(a1),a2); break;
case 0x36: /* close */
v0 = close(a0); break;
case 0x37: /* ioctl */
case 0x38: /* exit */
case 0x39: /* ?? */
case 0x3a: /* getc */
case 0x3b: /* putc */
return -1;
case 0x3c: /* getchar */
v0 = getchar(); break;
case 0x3d: /* putchar */
v0 = putchar(a0); break;
case 0x3e: /* gets */
{
char *base = (char*)baseaddr(a0);
char *ret = gets(base + a0);
v0 = PSADDR(ret,base);
}
break;
case 0x3f: /* puts */
v0 = puts(realaddr(a0)); break;
case 0x42: /* 0x42 firstfile */
{
int t = (int)firstfile((char *)realaddr(a0),
(struct DIRENTRY *)realaddr(a1));
if (t) t=a1;
v0 = t;
}
break;
case 0x43: /* 0x43 nextfile */
{
int t = (int)nextfile((struct DIRENTRY *)realaddr(a0));
if (t) t=a0;
v0 = t;
}
break;
case 0x51: /* Krom2RawAdd */
{
void *ret = Krom2RawAdd(a0);
v0 = PSADDR(ret,rom-0xbfc00000);
}
break;
default:
/* unsupport */
return -1;
}
return 0;
}
static int bios_c0()
{
switch(reg.r[9]) {
default:
/* unsupport */
return -1;
}
return 0;
}
static int bios_a0()
{
switch(reg.r[9]) {
case 0x00: /* open */
v0 = bios_open(realaddr(a0),a1); break;
case 0x01: /* lseek */
v0 = lseek(a0,a1,a2); break;
case 0x02: /* read */
printf("%d %x %d",(int)a0,(int)a1,(int)a2);
v0 = read(a0,realaddr(a1),a2); break;
case 0x03: /* write */
v0 = write(a0,realaddr(a1),a2); break;
case 0x04: /* close */
v0 = close(a0); break;
case 0x05: /* ioctl */
case 0x06: /* exit */
case 0x07: /* ?? */
case 0x08: /* getc */
case 0x09: /* putc */
return -1;
case 0x0a: /* todigit */
v0 = a0-'0'; break;
case 0x0b: /* atof */
{ union { double d; int lo,hi; } t;
t.d = atof(realaddr(a0));
v0 = t.lo;
v1 = t.hi;
}
break;
case 0x0c: /* strtoul */
{ char *base = baseaddr(a0);
char *endp;
v0 = strtoul(base+a0,&endp,a2);
if (a1) a1 = PSADDR2(endp,base);
}
break;
case 0x0d: /* strtol */
{ char *base = baseaddr(a0);
char *endp;
v0 = strtol(base+a0,&endp,a2);
if (a1) a1 = PSADDR2(endp,base);
}
break;
case 0x0e: /* abs */
case 0x0f: /* labs */
v0 = (a0>=0)?a0:-a0; break;
case 0x10: /* atoi */
case 0x11: /* atol */
v0 = atoi(realaddr(a0)); break;
case 0x12: /* atob */
return -1;
case 0x13: /* setjmp */
{ int *jmpbuf=realaddr(a0);
jmpbuf[0] = reg.r[31]; /* ra */
jmpbuf[1] = reg.r[29]; /* sp */
jmpbuf[2] = reg.r[28]; /* fp */
jmpbuf[3] = reg.r[16]; /* s0 */
jmpbuf[4] = reg.r[17]; /* s1 */
jmpbuf[5] = reg.r[18]; /* s2 */
jmpbuf[6] = reg.r[19]; /* s3 */
jmpbuf[7] = reg.r[20]; /* s4 */
jmpbuf[8] = reg.r[21]; /* s5 */
jmpbuf[9] = reg.r[22]; /* s6 */
jmpbuf[10] = reg.r[23]; /* s7 */
jmpbuf[11] = reg.r[28]; /* gp */
}
v0 = 0;
break;
case 0x14: /* longjmp */
{ int *jmpbuf=realaddr(a0);
reg.r[31] = jmpbuf[0]; /* ra */
reg.r[29] = jmpbuf[1]; /* sp */
reg.r[28] = jmpbuf[2]; /* fp */
reg.r[16] = jmpbuf[3]; /* s0 */
reg.r[17] = jmpbuf[4]; /* s1 */
reg.r[18] = jmpbuf[5]; /* s2 */
reg.r[19] = jmpbuf[6]; /* s3 */
reg.r[20] = jmpbuf[7]; /* s4 */
reg.r[21] = jmpbuf[8]; /* s5 */
reg.r[22] = jmpbuf[9]; /* s6 */
reg.r[23] = jmpbuf[10]; /* s7 */
reg.r[28] = jmpbuf[11]; /* gp */
}
v0 = a1;
break;
case 0x15: /* strcat */
v0 = a0; strcat(realaddr(a0),realaddr(a1)); break;
case 0x16: /* strncat */
v0 = a0; strncat(realaddr(a0),realaddr(a1),a2); break;
case 0x17: /* strcat */
v0 = strcmp(realaddr(a0),realaddr(a1)); break;
case 0x18: /* strncmp */
v0 = strncmp(realaddr(a0),realaddr(a1),a2); break;
case 0x19: /* strcpy */
v0 = a0; strcpy(realaddr(a0),realaddr(a1)); break;
case 0x1a: /* strncpy */
v0 = a0; strncpy(realaddr(a0),realaddr(a1),a2); break;
case 0x1b: /* strlen */
v0 = strlen(realaddr(a0)); break;
case 0x1c: /* index */
case 0x1e: /* strchr */
{ char *base = baseaddr(a0);
char *ret = strchr(base + a0,a1);
v0 = PSADDR(ret,base);
}
break;
case 0x1d: /* rindex */
case 0x1f: /* strrchr */
{ char *base = baseaddr(a0);
char *ret = strrchr(base + a0,a1);
v0 = PSADDR(ret,base);
}
break;
case 0x20: /* strpbrk */
{ char *base = baseaddr(a0);
char *ret = strpbrk(base + a0,realaddr(a1));
v0 = PSADDR(ret,base);
}
break;
case 0x21: /* strspn */
v0 = strspn(realaddr(a0),realaddr(a1)); break;
case 0x22: /* strcspn */
v0 = strcspn(realaddr(a0),realaddr(a1)); break;
case 0x23: /* strtok */
{ char *base = baseaddr(a0);
char *ret = strtok(base + a0,a1?realaddr(a1):(char*)a1);
v0 = PSADDR(ret,base);
}
break;
case 0x24: /* strstr */
{ char *base = baseaddr(a0);
char *ret = strstr(base + a0,realaddr(a1));
v0 = PSADDR(ret,base);
}
break;
case 0x25: /* toupper */
v0 = toupper(a0); break;
case 0x26: /* tolower */
v0 = tolower(a0); break;
case 0x27: /* bcopy */
memcpy(realaddr(a1),realaddr(a0),a2); break;
case 0x28: /* bzero */
memset(realaddr(a0),0,a1); break;
case 0x29: /* bcmp */
v0 = memcmp(realaddr(a0),realaddr(a1),a2); break;
case 0x2a: /* memcpy */
v0 = a0; memcpy(realaddr(a0),realaddr(a1),a2); break;
case 0x2b: /* memset */
v0 = a0; memset(realaddr(a0),a1,a2); break;
case 0x2c: /* memmove */
v0 = a0; memmove(realaddr(a0),realaddr(a1),a2); break;
case 0x2d: /* memcmp */
v0 = memcmp(realaddr(a0),realaddr(a1),a2); break;
case 0x2e: /* memchr */
{ char *base = baseaddr(a0);
char *ret = memchr(base + a0,a1,a2);
v0 = PSADDR(ret,base);
}
break;
case 0x2f: /* rand */
v0 = rand(); break;
case 0x30: /* srand */
srand(a0); break;
case 0x31: /* qsort */
qbase = baseaddr(a0);
qsub = a3;
qsort(qbase + a0,a1,a2,qcmp);
break;
case 0x32: /* strtod */
{ char *base = baseaddr(a0);
char *endp;
union { double d; int lo,hi; } t;
t.d = strtod(base+a0,&endp);
v0 = t.lo;
v1 = t.hi;
if (a1) a1 = PSADDR2(endp,base);
}
break;
case 0x33: /* malloc */
{
char *ret = bios_malloc(a0);
v0 = PSADDR(ret,heapbase);
}
break;
case 0x34: /* free */
bios_free(PCADDR(a0,heapbase));
break;
case 0x35: /* lsearch */
return -1;
/*
qbase = baseaddr(a0);
qsub = stack[4];
{
char *ret = lsearch(qbase+a0,qbase+a1,realaddr(a2),a3,qcmp);
v0 = PSADDR(ret,qbase);
}
break;
*/
case 0x36: /* bsearch */
qbase = baseaddr(a0);
qsub = stack[4];
{
char *ret = bsearch(qbase+a0,qbase+a1,a2,a3,qcmp);
v0 = PSADDR(ret,qbase);
}
break;
case 0x37: /* calloc */
{
char *ret = bios_calloc(a0,a1);
v0 = PSADDR(ret,heapbase);
}
break;
case 0x38: /* realloc */
{
char *ret = bios_realloc(PCADDR(a0,heapbase),a1);
v0 = PSADDR(ret,heapbase);
}
break;
case 0x39: /* InitHeap */
heapbase = baseaddr(a0);
bios_InitHeap(heapbase + a0,a1);
break;
case 0x3a: /* _exit */
return -1;
case 0x3b: /* getchar */
v0 = getchar(); break;
case 0x3c: /* putchar */
v0 = putchar(a0); break;
case 0x3d: /* gets */
{ char *base = (char*)baseaddr(a0);
char *ret = gets(base + a0);
v0 = PSADDR(ret,base);
}
break;
case 0x3e: /* puts */
v0 = puts(realaddr(a0)); break;
case 0x3f: /* printf */
/* ¼ */
{char *s = realaddr(a0);
// if (strstr(s,"%s")) {
// v0 = printf("%s",s);
// } else {
long *ptr = realaddr(sp);
ptr[1] = a1;
ptr[2] = a2;
ptr[3] = a3;
#ifdef __WATCOMC__
v0 = vprintf(s,(char*)(ptr+1));
#else
v0 = vprintf(s,*((va_list*)(ptr+1)));
#endif
// }
}
break;
case 0x46: /* GPU_dw */
{
int size;
long *ptr;
GP0_Write(0xa0000000);
GP0_Write((a1<<16)|(a0&0xffff));
GP0_Write((a3<<16)|(a2&0xffff));
size = (a2*a3+1)/2;
ptr = realaddr(stack[4]);
do {
GP0_Write(*ptr++);
} while(--size);
}
break;
case 0x47: /* mem2vram */
{
int size;
PRINTF("%d %d %d %d %x",(int)a0,(int)a1,(int)a2,(int)a3,(int)stack[4]);
GP0_Write(0xa0000000);
GP0_Write((a1<<16)|(a0&0xffff));
GP0_Write((a3<<16)|(a2&0xffff));
size = (a2*a3+1)/2;
GP1_Write(0x04000002);
hw_write32(0x1f8010f4,0);
hw_write32(0x1f8010f0,hw_read32(0x1f8010f0)|0x800);
hw_write32(0x1f8010a0,stack[4]);
hw_write32(0x1f8010a4,((size/16)<<16)|16);
hw_write32(0x1f8010a8,0x01000201);
}
break;
case 0x48: /* SendGPU */
GP1_Write(a0);
break;
case 0x49: /* GPU_cw */
GP0_Write(a0);
break;
case 0x4a: /* GPU_cwb */
{
long *ptr = realaddr(a0);
int size = a1;
while(size--) {
GP0_Write(*ptr++);
}
}
break;
case 0x4b: /* SendPackets */
GP1_Write(0x04000002);
hw_write32(0x1f8010f4,0);
hw_write32(0x1f8010f0,hw_read32(0x1f8010f0)|0x800);
hw_write32(0x1f8010a0,a0);
hw_write32(0x1f8010a4,0);
hw_write32(0x1f8010a8,0x010000401);
break;
case 0x4c: /* ??? */
hw_write32(0x1f8010a8,0x00000401);
GP0_Write(0x0400000);
GP0_Write(0x0200000);
GP0_Write(0x0100000);
break;
case 0x4d: /* GetGPUStatus */
v0 = GP1_Read();
break;
case 0x4e: /* GPU_sync */
break;
default:
/* unsupport */
return -1;
}
return 0;
}
#if 0
int bios_printf(char *fmt,int *arg)
{
int ch;
static char decimal = '.';
for(cnt=0;;) {
while((ch = *fmt++) && ch!='%') { putchar(ch); cnt++; }
if (ch=='\0') break;
rflag:
switch(*fmt++) {
case ' ': if (!sign) sign=' '; goto rflag;
case '#': flags |= ALT; goto rflag;
case '*':
case '-': flags |= LADJUST; goto rflag;
case '+': sign = '+'; goto rflag;
case '.': if (*fmt=='*') {}
case '0':
case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
case 'L': flags |= LONGDBL; goto rflag;
case 'h': flags |= SHORTINT; goto rflag;
case 'l': if (flags&LONGINT) flags |= LONGDBL; else flags = LONGINT;
goto rflag;
case 'q':
case 'c':
case 'D': flags |= LONGINT;
case 'd':
case 'i':
case 'E':
case 'e':
case 'f':
case 'g':
case 'G':
case 'n':
case 'O':
case 'o':
case 'p':
case 's':
case 'U': flags |= LONGINT;
case 'u':
case 'X':
case 'x':
}
}
}
#endif
int interrupt_handler()
{
int intr;
intr = hw_read16(0x1f801070) & hw_read16(0x1f801074); /* int reg & mask */
if (intr&1) { /* VSync interrupt */
pad_update();
}
hw_write16(0x1f801070,0);
hw_write32(0x1F8010F4,hw_read32(0x1F8010F4));
return 0;
}
int exception_handler()
{
if (!emulate_bios) return 0;
switch((CAUSE&0x3c)>>2) {
case E_Int:
/* WX^Û¶ */
memcpy(save_reg,reg.r,sizeof(save_reg));
if (jmpbuf) {
/* HookEntryIntÌÝèɧäªÚé */
bios_longjmp(jmpbuf);
v0 = 1;
PC = reg.r[31];
hw_write32(0x1f801070,0xFFFFFFFF);
} else {
interrupt_handler();
PC = EPC;
SR = (SR & ~0xf)| ((SR>>2)&0xf); /* rfe */
}
break;
case E_Sys:
switch(reg.r[4]) {
case 1: SR &= ~0x404; PC = EPC+4; break;
case 2: SR |= 0x404; PC = EPC+4; break;
default: return -1;
}
SR = (SR & ~0xf)| ((SR>>2)&0xf); /* rfe */
break;
default:
return -1;
}
return 0;
}
/*
FONTX format
idx siz
0 6 id "FONTX"
6 8 name
14 1 width
15 1 height
16 1 type (0=ANK 1=Japanese)
ANK:
17 font data (0x00-0xff)
Japanese:
17 1 Number of code table
18 2 start of code
20 2 end of code
.
.
18+N*4 font data
*/
void *fileload(char *file,void *buf)
{
FILE *fp;
int fsize;
fp = fopen(file,"rb");
if (fp==NULL) return NULL;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);
if (buf!=NULL || (buf = malloc(fsize))!=NULL) {
fread(buf,1,fsize,fp);
}
fclose(fp);
return buf;
}
static char *fontfile = "JPNZN16X.X11";
int bios_init(void)
{
/* font load at rom area */
font = (void*)(rom+0x20000);
fileload(fontfile,font);
return 0;
}